﻿using System.Windows.Input;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;

namespace Ebt.Mvvm.Behaviors
{
    /// <summary>
    /// Allows to bind and execute a command on Enter key pressing.
    /// It also ensures that you binding receives the most recent value of the <see cref="TextBox.Text"/> or <see cref="PasswordBox.Password"/> property.
    /// </summary>
    public static class DefaultButtonBehavior
    {
        public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached("Command", typeof (ICommand), typeof (DefaultButtonBehavior),
            new PropertyMetadata(DependencyProperty.UnsetValue, OnCommandPropertyChanged));

        private static void OnCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var element = d as FrameworkElement;
            if (element != null)
                element.KeyDown += OnKeyDown;

            var textBox = d as TextBox;
            if (textBox != null)
                textBox.TextChanged += OnTextChanged;
        }

        private static void OnKeyDown(object sender, KeyRoutedEventArgs e)
        {
            if (e.Key != VirtualKey.Enter || e.KeyStatus.RepeatCount == 0) // For some reason KeyDown event raises 2 times. First time RepeatCount equals 0.
                return;

            var element = sender as FrameworkElement;
            var command = GetCommand(element);
            if (command.CanExecute(null))
            {
                command.Execute(null);
            }
        }

        public static void SetCommand(DependencyObject d, ICommand value)
        {
            d.SetValue(CommandProperty, value);
        }

        public static ICommand GetCommand(DependencyObject d)
        {
            return (ICommand) d.GetValue(CommandProperty);
        }

        private static void OnTextChanged(object sender, TextChangedEventArgs e)
        {
            var textBox = (TextBox)sender;
            SetText(textBox, textBox.Text);
        }

        #region Text attached property

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.RegisterAttached("Text", typeof (string), typeof (DefaultButtonBehavior), null);

        public static void SetText(DependencyObject d, string value)
        {
            d.SetValue(TextProperty, value);
        }

        public static string GetText(DependencyObject d)
        {
            return (string) d.GetValue(TextProperty);
        }

        #endregion
    }
}
